package jgcp.master.management;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import jgcp.common.Task;
import jgcp.common.TaskStore;
import jgcp.master.network.WorkerList;
/**
 * 
 * @Date 31/05/2009
 * @author Jie Zhao (288654)
 * @version 1.0
 */
public class Worker_Task implements Observer {
	private Worker_Task() {
	}

	private static Worker_Task instance = new Worker_Task();
	private Hashtable<Integer, List<Integer>> worker_task = new Hashtable<Integer, List<Integer>>();
	private List<Integer> workerList = null;

	public void update(Observable o, Object arg) {
		updateList();
		reschedule();
	}
	public void reschedule()
	{
		workerList = WorkerList.getInstance().getWorkerList();
		if(workerList.size() < worker_task.size())	//worker removed
		{
			Enumeration<Integer> keys = worker_task.keys();
			while(keys.hasMoreElements())
			{
				Integer workerId = keys.nextElement();
				if(!workerList.contains(workerId))
				{

					List<Integer> tasks_reschedule = getTasks(workerId);
					for(Integer ii:tasks_reschedule)
					{
						Task t = TaskStore.getInstance().retrieve(ii);
						if(t!=null)TaskQueue.getInstance().put(t);
					}
					worker_task.remove(workerId);
				}
			}
		}
	}
	public static Worker_Task getInstance() {
		return instance;
	}

	private void updateList() {
		workerList = WorkerList.getInstance().getWorkerList();
		for (Integer i : workerList) {
			if (!worker_task.containsKey(i)) {
				worker_task.put(i, new ArrayList<Integer>());
			}
		}
	}

	public int findWorker(int taskId)
	{
		Enumeration<Integer> workerids = worker_task.keys();
		while(workerids.hasMoreElements())
		{
			int idx = workerids.nextElement();
			List<Integer> taskids = worker_task.get(idx);
			if(taskids.contains(taskId))
			{
				return idx;
			}
		}
		return -1;
	}
	
	/**
	 * Assign a task to a worker.
	 * 
	 * @param workerId
	 * @param taskId
	 */
	public boolean assign(int workerId, int taskId) {
//		System.out.println("Assigned Task "+taskId+" to worker "+workerId);
		List<Integer> tasks = worker_task.get(workerId);
		if (tasks != null) {
			if(!tasks.contains(taskId))tasks.add(taskId);
			return true;
		}
		return false;
	}

	/**
	 * 
	 * @param workerId
	 * @return
	 */
	public List<Integer> getTasks(int workerId)
	{
		List<Integer> result = worker_task.get(workerId);
		if(result == null)return new ArrayList<Integer>();
		return new ArrayList<Integer>(result);
	}
}
